home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-10 | 20.9 KB | 718 lines | [TEXT/CWIE] |
- //MetaFileView.cp
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- //
- // Quickdraw 3D sample code
- //
- // Rick Evans, AppleLink: DEVSUPPORT (devsupport@applelink.apple.com)
- //
- // The following functions were adapted from the QD3D sample MetaFileRead.
- //
- // ©1996 Apple Computer Inc., All Rights Reserved
- //
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- // for QuickDraw 3D
- #include <QD3D.h>
- #include <QD3DMath.h>
- #include <QD3DDrawContext.h>
- #include <QD3DShader.h>
- #include <QD3DTransform.h>
- #include <QD3DGroup.h>
- #include <QD3DCamera.h>
- #include <QD3DErrors.h>
- #include <QD3DStyle.h>
- #include <QD3DView.h>
- #include <QD3DRenderer.h>
- #include <QD3DLight.h>
- #include <QD3DStorage.h>
- #include <QD3DIO.h>
-
- #include "View3DMF.h"
- #include "MetaFileView.h"
-
- //-----------------------------------------------------------------------------------------------
- // private prototypes:
- //-----------------------------------------------------------------------------------------------
- static TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow, Rect* theRect) ;
- static TQ3FileObject MyGetNewFile( PluginInstance* This ) ;
- static TQ3CameraObject MyNewCamera(WindowPtr theWindow) ;
- static TQ3GroupObject MyNewLights( void ) ;
- static TQ3Status MyAddShaderToGroup( TQ3GroupObject group ) ;
- static TQ3Status MyReadModelFromFile( TQ3FileObject theFile, TQ3GroupObject myGroup) ;
- static TQ3Status SubmitScene( PluginInstance* theDocument ) ;
- static TQ3Status GetDocumentGroupBoundingBox(PluginInstance* t, TQ3BoundingBox *viewBBox) ;
- static void GetGroupBBox(PluginInstance* theDocument, TQ3BoundingBox *viewBBox) ;
- static char* TypeNameFromQ3Obj(char* nm, TQ3Object obj) ;
- static char* NameFromQ3Type(char* nm, TQ3ObjectType typ) ;
-
-
- //------------------------------------------------------------------------------------
- // MyNewView:
- //------------------------------------------------------------------------------------
-
- TQ3ViewObject MyNewView(GrafPtr theWindow, Rect* theRect)
- {
- TQ3Status myStatus;
- TQ3ViewObject myView;
- TQ3DrawContextObject myDrawContext;
- TQ3RendererObject myRenderer;
- TQ3CameraObject myCamera;
- TQ3GroupObject myLights;
-
- myView = ::Q3View_New();
- if (myView == NULL)
- goto bailnow;
-
- // Create and set draw context.
- if ((myDrawContext = MyNewDrawContext(theWindow, theRect)) == nil )
- goto bail;
-
- myStatus = ::Q3View_SetDrawContext(myView, myDrawContext) ;
-
- ::Q3Object_Dispose( myDrawContext ) ;
-
- if (myStatus == kQ3Failure)
- goto bail;
-
- // Create and set renderer.
- //
- // hacky way to do this, but since I wanted these snippets to have
- // a minimal interface, this will suffice
- //
- // change the next line to “#if 1” to use the WF renderer
-
- #if 0
-
- // this would use the wireframe renderer
- myRenderer = ::Q3Renderer_NewFromType(kQ3RendererTypeWireFrame) ;
- if (myRenderer == NULL)
- goto bail;
-
- #else
-
- // this would use the interactive software renderer
- myRenderer = ::Q3Renderer_NewFromType(kQ3RendererTypeInteractive) ;
- if (myRenderer == NULL)
- goto bail;
-
- #endif
-
- myStatus = ::Q3View_SetRenderer(myView, myRenderer) ;
-
- ::Q3Object_Dispose( myRenderer ) ;
-
- if ( myStatus == kQ3Failure )
- goto bail;
-
- // Create and set camera.
- myCamera = MyNewCamera(theWindow) ;
- if (myCamera == NULL)
- goto bail;
-
- myStatus = ::Q3View_SetCamera(myView, myCamera);
-
- ::Q3Object_Dispose( myCamera ) ;
-
- if ( myStatus == kQ3Failure )
- goto bail;
-
- // Create and set lights.
- myLights = MyNewLights() ;
- if (myLights == NULL)
- goto bail;
-
- myStatus = ::Q3View_SetLightGroup(myView, myLights) ;
-
- ::Q3Object_Dispose(myLights);
-
- if ( myStatus == kQ3Failure )
- goto bail;
-
- // Done!!!
- return ( myView );
-
- // If any of the above failed, dispose the view object and return NULL.
- bail:
- ::Q3Object_Dispose( myView ) ; // disposing view disposes all objects set in view
-
- bailnow:
- return ( NULL );
- }
-
- //------------------------------------------------------------------------------------
- // MyNewDrawContext:
- //------------------------------------------------------------------------------------
- TQ3DrawContextObject MyNewDrawContext(WindowPtr theWindow, Rect* theRect)
- {
- //TQ3DrawContextData myDrawContextData;
- TQ3MacDrawContextData myMacDrawContextData;
- TQ3ColorARGB ClearColor;
- TQ3DrawContextObject myDrawContext ;
-
- ClearColor.a = 1.0;
- ClearColor.r = 1.0;
- ClearColor.g = 1.0;
- ClearColor.b = 1.0;
-
- // Fill in draw context data.
- myMacDrawContextData.drawContextData.pane.min.x = theRect->left;
- myMacDrawContextData.drawContextData.pane.min.y = theRect->top;
- myMacDrawContextData.drawContextData.pane.max.x = theRect->right;
- myMacDrawContextData.drawContextData.pane.max.y = theRect->bottom;
-
- myMacDrawContextData.drawContextData.clearImageMethod = kQ3ClearMethodWithColor;
- myMacDrawContextData.drawContextData.clearImageColor = ClearColor;
-
- myMacDrawContextData.drawContextData.paneState = kQ3True;
- myMacDrawContextData.drawContextData.maskState = kQ3False;
-
- myMacDrawContextData.drawContextData.doubleBufferState = kQ3True;
-
- myMacDrawContextData.window = (CGrafPtr) theWindow; // this is the window associated with the view
- myMacDrawContextData.library = kQ3Mac2DLibraryNone;
- myMacDrawContextData.viewPort = nil;
- myMacDrawContextData.grafPort = (CGrafPtr) theWindow;
-
- // Create draw context and return it, if it’s nil the caller must handle
- myDrawContext = ::Q3MacDrawContext_New(&myMacDrawContextData) ;
-
- return myDrawContext ;
- }
-
- //------------------------------------------------------------------------------------
- // MyNewCamera:
- //------------------------------------------------------------------------------------
- TQ3CameraObject MyNewCamera(WindowPtr theWindow)
- {
- TQ3CameraObject myCamera;
- TQ3CameraData myCameraData;
- TQ3ViewAngleAspectCameraData myViewAngleCameraData;
- TQ3Point3D cameraFrom = { 0.0, 0.0, 30.0 };
- TQ3Point3D cameraTo = { 0.0, 0.0, 0.0 };
- TQ3Vector3D cameraUp = { 0.0, 1.0, 0.0 };
-
- float fieldOfView = .52359333333;
- float hither = 0.001;
- float yon = 1000;
-
- // Fill in camera data.
- myCameraData.placement.cameraLocation = cameraFrom;
- myCameraData.placement.pointOfInterest = cameraTo;
- myCameraData.placement.upVector = cameraUp;
-
- myCameraData.range.hither = hither;
- myCameraData.range.yon = yon;
-
- myCameraData.viewPort.origin.x = -1.0;
- myCameraData.viewPort.origin.y = 1.0;
- myCameraData.viewPort.width = 2.0;
- myCameraData.viewPort.height = 2.0;
-
- myViewAngleCameraData.cameraData = myCameraData;
- myViewAngleCameraData.fov = fieldOfView ;
-
- // set up the aspect ratio based on the window
- myViewAngleCameraData.aspectRatioXToY =
- (float) (theWindow->portRect.right - theWindow->portRect.left) /
- (float) (theWindow->portRect.bottom - theWindow->portRect.top);
-
- myCamera = ::Q3ViewAngleAspectCamera_New(&myViewAngleCameraData);
-
- // Return the camera.
- return ( myCamera );
- }
-
-
- //------------------------------------------------------------------------------------
- // MyNewLights:
- //------------------------------------------------------------------------------------
- TQ3GroupObject MyNewLights()
- {
- TQ3GroupPosition myGroupPosition;
- TQ3GroupObject myLightList;
- TQ3LightData myLightData;
- TQ3PointLightData myPointLightData;
- TQ3DirectionalLightData myDirectionalLightData;
- TQ3LightObject myAmbientLight, myPointLight, myFillLight;
- TQ3Point3D pointLocation = { -10.0, 0.0, 10.0 };
- TQ3Vector3D fillDirection = { 10.0, 0.0, 10.0 };
- TQ3ColorRGB WhiteLight = { 1.0, 1.0, 1.0 };
-
- // Set up light data for ambient light. This light data will be used for point and fill
- // light also.
-
- myLightData.isOn = kQ3True;
- myLightData.color = WhiteLight;
-
- // Create ambient light.
- myLightData.brightness = .2;
- myAmbientLight = ::Q3AmbientLight_New(&myLightData);
- if ( myAmbientLight == nil )
- goto bail;
-
- // Create point light.
- myLightData.brightness = 1.0;
- myPointLightData.lightData = myLightData;
- myPointLightData.castsShadows = kQ3False;
- myPointLightData.attenuation = kQ3AttenuationTypeNone;
- myPointLightData.location = pointLocation;
- myPointLight = ::Q3PointLight_New(&myPointLightData);
- if ( myPointLight == nil )
- goto bail;
-
- // Create fill light.
- myLightData.brightness = .2;
- myDirectionalLightData.lightData = myLightData;
- myDirectionalLightData.castsShadows = kQ3False;
- myDirectionalLightData.direction = fillDirection;
- myFillLight = ::Q3DirectionalLight_New(&myDirectionalLightData);
- if ( myFillLight == nil )
- goto bail;
-
- // Create light group and add each of the lights into the group.
- myLightList = Q3LightGroup_New();
- if ( myLightList == nil )
- goto bail;
- myGroupPosition = ::Q3Group_AddObject(myLightList, myAmbientLight);
- if ( myGroupPosition == 0 )
- goto bail;
- myGroupPosition = ::Q3Group_AddObject(myLightList, myPointLight);
- if ( myGroupPosition == 0 )
- goto bail;
- myGroupPosition = ::Q3Group_AddObject(myLightList, myFillLight);
- if ( myGroupPosition == 0 )
- goto bail;
-
- ::Q3Object_Dispose( myAmbientLight ) ;
- ::Q3Object_Dispose( myPointLight ) ;
- ::Q3Object_Dispose( myFillLight ) ;
-
- // Done!
- return ( myLightList );
-
- bail:
- // If any of the above failed, then return nothing!
- return ( nil );
- }
-
- //------------------------------------------------------------------------------------
- // MyAddShaderToGroup:
- //------------------------------------------------------------------------------------
- // attach a shader to the group
-
- TQ3Status MyAddShaderToGroup( TQ3GroupObject group )
- {
- TQ3ShaderObject illuminationShader = ::Q3PhongIllumination_New();
- if (illuminationShader == NULL)
- return (kQ3Failure);
-
- ::Q3Group_AddObject(group, illuminationShader);
- ::Q3Object_Dispose(illuminationShader);
- return(kQ3Success);
- }
-
- //------------------------------------------------------------------------------------
- // MyReadModelFromFile:
- //----------------------------------------------------------------------------------
- // read model from file object into the supplied group
-
- TQ3Status MyReadModelFromFile( TQ3FileObject theFile,TQ3GroupObject myGroup)
- {
- if(theFile != NULL) {
-
- TQ3Object myTempObj ;
- TQ3Boolean isEOF ;
-
-
- // read objects from the file
- do {
-
- myTempObj = ::Q3File_ReadObject( theFile );
-
- if( myTempObj != NULL ) {
- // we only want the object in our main group if we can draw it
- if ( ::Q3Object_IsDrawable( myTempObj) )
- ::Q3Group_AddObject( myGroup, myTempObj ) ;
-
- // we either added the object to the main group, or we don't care
- // so we can safely dispose of the object
- ::Q3Object_Dispose( myTempObj ) ;
- }
-
- // check to see if we reached the end of file yet
- isEOF = ::Q3File_IsEndOfFile( theFile );
-
- } while (isEOF == kQ3False);
- }
-
- if( myGroup != NULL )
- return kQ3Success ;
- else
- return kQ3Failure ;
- }
- //------------------------------------------------------------------------------------
- // MyGetNewFile:
- //------------------------------------------------------------------------------------
- TQ3FileObject
- MyGetNewFile( PluginInstance* This)
-
- {
- TQ3StorageObject myStorageObj;
- TQ3FileObject myFileObj;
-
- myStorageObj = ::Q3HandleStorage_New(This->fBuffer,This->fBufferLength) ;
- if (myStorageObj == NULL)
- {
- return NULL;
- }
-
- myFileObj = ::Q3File_New() ;
- if (myFileObj == NULL)
- {
- ::Q3Object_Dispose(myStorageObj) ;
- return NULL;
- }
-
- // Set the storage for the file object
- ::Q3File_SetStorage(myFileObj, myStorageObj) ;
- ::Q3Object_Dispose(myStorageObj) ;
-
- return myFileObj;
- }
-
- //------------------------------------------------------------------------------------
- // MyNewModelFromBuffer:
- //------------------------------------------------------------------------------------
- // read model from buffer into the supplied group
- //----------------------------------------------------------------------------------
-
- TQ3GroupObject
- MyNewModelFromBuffer(PluginInstance* This)
- {
- TQ3GroupObject myGroup = NULL ;
- TQ3Boolean isText = kQ3False ;
- TQ3FileMode myFileMode = 0;
- TQ3FileObject theFile;
- TQ3Status myStatus;
-
- // Create a ordered group for the complete model.
- if ((myGroup = ::Q3DisplayGroup_New()) == NULL )
- return NULL;
-
- MyAddShaderToGroup( myGroup ) ;
-
- theFile = MyGetNewFile( This ) ;
- if (theFile == NULL)
- {
- ::Q3Object_Dispose(myGroup);
- return NULL ;
- }
-
- // Open the file object
- myStatus = ::Q3File_OpenRead( theFile, NULL ) ;
- if (myStatus != kQ3Success)
- {
- ::Q3Object_Dispose(theFile);
- ::Q3Object_Dispose(myGroup);
- return NULL ;
- }
-
- if( MyReadModelFromFile( theFile, myGroup ) == 0)
- DebugStr("\pMetafile data read is null") ;
-
- // close and dispose of the file object
- ::Q3File_Close(theFile);
- ::Q3Object_Dispose(theFile);
-
- return myGroup ;
- }
-
- //------------------------------------------------------------------------------------
- // SubmitScene:
- //------------------------------------------------------------------------------------
- // Submit the scene for rendering/fileIO and picking
- TQ3Status SubmitScene( PluginInstance* theDocument )
- {
- TQ3Vector3D globalScale;
- TQ3Vector3D globalTranslate;
-
- globalScale.x = globalScale.y = globalScale.z = theDocument->fGroupScale;
- globalTranslate = *(TQ3Vector3D *)&theDocument->fGroupCenter;
- ::Q3Vector3D_Scale(&globalTranslate, -1, &globalTranslate);
- ::Q3Style_Submit(theDocument->fInterpolation, theDocument->fView);
- ::Q3Style_Submit(theDocument->fBackFacing , theDocument->fView);
- ::Q3Style_Submit(theDocument->fFillStyle, theDocument->fView);
-
- ::Q3MatrixTransform_Submit( &theDocument->fRotation, theDocument->fView);
-
- ::Q3ScaleTransform_Submit(&globalScale, theDocument->fView);
- ::Q3TranslateTransform_Submit(&globalTranslate, theDocument->fView);
- ::Q3DisplayGroup_Submit( theDocument->fModel, theDocument->fView);
-
- return kQ3Success ;
- }
-
- //------------------------------------------------------------------------------------
- // GetDocumentGroupBoundingBox:
- //------------------------------------------------------------------------------------
- TQ3Status GetDocumentGroupBoundingBox(
- PluginInstance* theDocument,
- TQ3BoundingBox *viewBBox)
- {
- TQ3Status status;
- TQ3ViewStatus viewStatus ;
-
- status = ::Q3View_StartBoundingBox( theDocument->fView, kQ3ComputeBoundsApproximate );
- do {
- status = SubmitScene( theDocument ) ;
- } while((viewStatus = ::Q3View_EndBoundingBox( theDocument->fView, viewBBox )) == kQ3ViewStatusRetraverse );
- return status ;
- }
-
- //------------------------------------------------------------------------------------
- // GetGroupBBox:
- //------------------------------------------------------------------------------------
- void GetGroupBBox(
- PluginInstance* theDocument,
- TQ3BoundingBox *viewBBox)
- {
- TQ3Point3D from = { 0.0, 0.0, 1.0 };
- TQ3Point3D to = { 0.0, 0.0, 0.0 };
- TQ3Vector3D up = { 0.0, 1.0, 0.0 };
-
- float fieldOfView = .52359333333;
- float hither = 0.5;
- float yon = 1.5;
- TQ3GroupObject mainGroup = theDocument->fModel ;
-
- TQ3Status status;
-
- #ifdef BETA_1_BUILD
- ::Q3View_StartBounds( theDocument->fView );
-
- status = ::Q3DisplayGroup_BoundingBox(mainGroup,
- viewBBox,
- kQ3ComputeBoundsApproximate,
- viewObject);
-
- ::Q3View_EndBounds( theDocument->fView );
- #else
- status = GetDocumentGroupBoundingBox( theDocument , viewBBox) ;
- #endif
-
- //
- // If we have a point model, then the "viewBBox" would end up
- // being a "singularity" at the location of the point. As
- // this bounding "box" is used in setting up the camera spec,
- // we get bogus input into Escher.
-
- {
- float xSize, ySize, zSize;
-
- xSize = viewBBox->max.x - viewBBox->min.x;
- ySize = viewBBox->max.y - viewBBox->min.y;
- zSize = viewBBox->max.z - viewBBox->min.z;
-
- if (xSize <= kQ3RealZero &&
- ySize <= kQ3RealZero &&
- zSize <= kQ3RealZero) {
-
- viewBBox->max.x += 0.0001;
- viewBBox->max.y += 0.0001;
- viewBBox->max.z += 0.0001;
-
- viewBBox->min.x -= 0.0001;
- viewBBox->min.y -= 0.0001;
- viewBBox->min.z -= 0.0001;
- }
- }
- }
-
- //------------------------------------------------------------------------------------
- // AdjustCamera:
- //------------------------------------------------------------------------------------
- TQ3Point3D AdjustCamera(
- PluginInstance* theDocument,
- short winWidth,
- short winHeight)
- {
- float fieldOfView;
- float hither;
- float yon;
- TQ3CameraPlacement placement;
- TQ3CameraRange range;
- TQ3BoundingBox viewBBox;
- long fromAxis;
- float maxDimension;
- float xSize, ySize, zSize;
- float weights[2] = { 0.5, 0.5 };
- TQ3Point3D points[2];
- TQ3Vector3D viewVector;
- TQ3Vector3D normViewVector;
- TQ3Vector3D eyeToFrontClip;
- TQ3Vector3D eyeToBackClip;
- float viewDistance;
- TQ3Vector3D diagonalVector;
- float ratio;
- TQ3CameraObject camera;
-
- TQ3ViewObject theView = theDocument->fView ;
-
- TQ3Point3D *documentGroupCenter = &theDocument->fGroupCenter ;
- float *documentGroupScale = &theDocument->fGroupScale ;
-
- ::Q3View_GetCamera( theView, &camera);
- GetGroupBBox( theDocument, &viewBBox);
-
- /*
- * If we have a point model, then the "viewBBox" would end up
- * being a "singularity" at the location of the point. As
- * this bounding "box" is used in setting up the camera spec,
- * we get bogus input into Escher.
- */
- xSize = viewBBox.max.x - viewBBox.min.x;
- ySize = viewBBox.max.y - viewBBox.min.y;
- zSize = viewBBox.max.z - viewBBox.min.z;
-
- if (xSize <= kQ3RealZero &&
- ySize <= kQ3RealZero &&
- zSize <= kQ3RealZero) {
- viewBBox.max.x += 0.0001;
- viewBBox.max.y += 0.0001;
- viewBBox.max.z += 0.0001;
-
- viewBBox.min.x -= 0.0001;
- viewBBox.min.y -= 0.0001;
- viewBBox.min.z -= 0.0001;
- }
-
- points[0] = viewBBox.min;
- points[1] = viewBBox.max;
-
- ::Q3Point3D_AffineComb(points, weights, 2, documentGroupCenter);
-
- /*
- * The "from" point is on a vector perpendicular to the plane
- * in which the bounding box has greatest dimension. As "up" is
- * always in the positive y direction, look at x and z directions.
- */
- xSize = viewBBox.max.x - viewBBox.min.x;
- zSize = viewBBox.max.z - viewBBox.min.z;
-
- if (xSize > zSize) {
- fromAxis = kQ3AxisZ;
- } else {
- fromAxis = kQ3AxisX;
- }
-
- /*
- * Compute the length of the diagonal of the bounding box.
- *
- * The hither and yon planes are adjusted so that the
- * diagonal of the bounding box is 7/8 the size of the
- * minimum dimension of the view frustum. The diagonal is used instead
- * of the maximum size (in x, y, or z) so that when you rotate
- * the object, the corners don't get clipped out.
- */
- ::Q3Point3D_Subtract(
- &viewBBox.max,
- &viewBBox.min,
- &diagonalVector);
-
- maxDimension = ::Q3Vector3D_Length(&diagonalVector);
- maxDimension *= 8.0 / 7.0;
-
- ratio = 1.0 / maxDimension;
-
- *documentGroupScale = ratio;
-
- ::Q3Camera_GetPlacement(camera, &placement);
-
- ::Q3Point3D_Subtract(
- &placement.cameraLocation,
- &placement.pointOfInterest,
- &viewVector);
-
- viewDistance = ::Q3Vector3D_Length(&viewVector);
-
- ::Q3Vector3D_Normalize(&viewVector, &normViewVector);
-
- ::Q3Vector3D_Scale(&normViewVector,
- viewDistance - ratio * maxDimension/2.0,
- &eyeToFrontClip);
-
- ::Q3Vector3D_Scale(&normViewVector,
- viewDistance + ratio * maxDimension/2.0,
- &eyeToBackClip);
-
- hither = ::Q3Vector3D_Length(&eyeToFrontClip);
- yon = ::Q3Vector3D_Length(&eyeToBackClip);
-
- fieldOfView = 2 * atan((ratio * maxDimension/2.0)/hither);
-
- range.hither = hither;
- range.yon = yon;
-
- ::Q3Camera_SetRange(camera, &range);
-
- ::Q3ViewAngleAspectCamera_SetFOV(
- camera, fieldOfView);
-
- ::Q3ViewAngleAspectCamera_SetAspectRatio(
- camera, (float) winWidth / (float) winHeight);
-
- ::Q3Object_Dispose(camera);
-
- return( *documentGroupCenter );
- }
-
- //------------------------------------------------------------------------------------
- // NameFromType:
- //------------------------------------------------------------------------------------
- char* NameFromQ3Type(char* nm, TQ3ObjectType typ)
- {
- BlockMove(&typ, nm, 4);
- nm[4] = 0;
- return nm;
- }
-
- //------------------------------------------------------------------------------------
- // TypeNameOfQ3Object:
- //------------------------------------------------------------------------------------
- char* TypeNameFromQ3Obj(char* nm, TQ3Object obj)
- {
- TQ3ObjectType typ = ::Q3Object_GetLeafType(obj);
-
- return NameFromQ3Type(nm,typ);
- }
- //------------------------------------------------------------------------------------
- // DocumentDraw3DData:
- //------------------------------------------------------------------------------------
-
- // assumes the port is set up before being called
- TQ3Status DocumentDraw3DData( PluginInstance* theDocument )
- {
- TQ3Status theStatus = kQ3Failure;
-
- if (theDocument->fBusy ) // Do not draw if we are not done.
- {
- //NPN_Status(theDocument, "Tried to draw before data finished loading.");
- return kQ3Failure;
- }
-
- if (theDocument->fModel == NULL) // Do not draw if nothing's there.
- {
- //NPN_Status(theDocument, "Tried to draw, but no data received.");
- return kQ3Failure;
- }
-
- ::Q3View_StartRendering(theDocument->fView) ;
- do {
- theStatus = SubmitScene( theDocument ) ;
-
- } while (::Q3View_EndRendering(theDocument->fView) == kQ3ViewStatusRetraverse );
-
- return theStatus ;
- }
-
-